// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包测试日志在测试和包操作系统之间提供了一个反向通道通信路径
// 以便cmd/go可以查看测试参考的环境变量和文件。
package testlog

import "sync/atomic"

// 接口是测试记录器所需的接口。
// 操作系统包将调用接口的方法，以指示
// 它正在检查给定的环境变量或文件。
// 多个goroutine可以同时调用这些方法。
type Interface interface {
	Getenv(key string)
	Stat(file string)
	Open(file string)
	Chdir(dir string)
}

// 记录器是当前记录器接口。
// 我们在测试启动
// 与初始化期间启动的goroutines竞争时使用原子.Value。
// 这一定不会导致种族检测器故障，尽管它仍然会导致有限的可见性
// 无法准确了解这些Goroutine的工作。
var logger atomic.Value

// SetLogger为当前进程设置测试记录器实现。
// 在进程启动时只能调用一次。
func SetLogger(impl Interface) {
	if logger.Load() != nil {
		panic("testlog: SetLogger must be called only once")
	}
	logger.Store(&impl)
}

// 记录器返回当前测试记录器实现。
// 如果没有记录器，则返回nil。
func Logger() Interface {
	impl := logger.Load()
	if impl == nil {
		return nil
	}
	return *impl.(*Interface)
}

// Getenv调用Logger（）.Getenv（如果已设置记录器）。
func Getenv(name string) {
	if log := Logger(); log != nil {
		log.Getenv(name)
	}
}

// Open调用Logger（）。如果已设置记录器，则打开。
func Open(name string) {
	if log := Logger(); log != nil {
		log.Open(name)
	}
}

// Stat调用Logger（）.Stat（如果已设置记录器）。
func Stat(name string) {
	if log := Logger(); log != nil {
		log.Stat(name)
	}
}
